iT邦幫忙

2

Javascript 進階 9-2 與傳統函式不同之處

  • 分享至 

  • xImage
  •  

這篇文章要來介紹箭頭函式跟傳統函式的差別~

1. 箭頭函式沒有 arguments 參數

之前在傳統函式有介紹到,參數的傳入有一個 arguments 參數會來承接所有船入的參數,並且使用**類陣列(Array-liked)**的方式記錄起來。

const nums = function () {
    console.log(arguments);
}

nums(1,2,3,4,6,7,8,500,10);

https://ithelp.ithome.com.tw/upload/images/20200519/20121770Lz0A7dz7Sg.png

但箭頭函式則沒有這個參數,那麼當如果我們需要記錄傳進來的參數的時候,該怎麼辦呢?

const nums = () => {
    console.log(arguments);
}

nums(1,2,3,4,6,7,8,500,10);

https://ithelp.ithome.com.tw/upload/images/20200519/20121770hnX57aIxZQ.png

這個時候就可以使用其餘參數運算子來解決這個問題,利用三個點+自定義變數名稱,就可以將參數的內容以陣列的方式記錄在變數上嚕!

const nums = (...arg) => {
    console.log(arg);
}

nums(1,2,3,4,6,7,8,500,10);

https://ithelp.ithome.com.tw/upload/images/20200519/20121770iNz9UaxkjO.png

2. This 綁定的差異

箭頭函式沒有自己的 This,怎麼說呢?

我們先來看看範例~

var myName = '全域';
var person = {
    myName: '小明',
    callName: function () {
        console.log('1', this.myName);

        setTimeout(function () {
            console.log('2', this.myName);
            console.log('3', this);
        }, 10);
    }
}

person.callName();

看完這樣的程式碼,我們可以知道 callName 這個函式中,this的指向會是 person 這個物件。
另外,setTimeout 因為傳入的是 callback function ,所以這裡面的作用域的 this 指向是全域的物件 window。

結果很明顯會是:

https://ithelp.ithome.com.tw/upload/images/20200519/20121770K3rK7GohhE.png

那麼我們稍微改動一下程式碼,把 callback function 改成箭頭函式的寫法,看看 this 會怎麼指向~

var myName = '全域';
var person = {
    myName: '小明',
    callName: function () {
        console.log('1', this.myName);

        setTimeout(() => {
            console.log('2', this.myName);
            console.log('3', this);
        }, 10);
    }
}

person.callName();

https://ithelp.ithome.com.tw/upload/images/20200519/20121770cBUtbQ7hJw.png

可以看到,this 的指向變成了外層作用域的 person。

那麼這個時候,再把 callName 的傳統函式也改成箭頭函式的寫法的話呢?

var myName = '全域';
var person = {
    myName: '小明',
    callName: () => {
        console.log('1', this.myName);

        setTimeout(() => {
            console.log('2', this.myName);
            console.log('3', this);
        }, 10);
    }
}

person.callName();

https://ithelp.ithome.com.tw/upload/images/20200519/20121770jSzsaiVvt6.png

很明顯,改成箭頭函式以後,this的指向就跑到全域的物件 window 身上。

而且不管埋幾層都一樣~

var odin = '1';
var obj = {
    odin: '2',
    arrfn: () => {
        console.log('2',this, this.odin)
        setTimeout(() => {
            console.log('2-setTimeout',this, this.odin)
        }, 10);
    },
    obj: {
        odin: '3',
        arrfn: () => console.log('3',this, this.odin),
        obj: {
            odin: '4',
            arrfn: function () { console.log('4',this, this.odin)},
            obj: {
                odin: '5',
                arrfn: function () {
                    console.log('5',this, this.odin)
                    setTimeout(() => {
                        console.log('5-setTimeout',this, this.odin)
                    }, 10);
                },
            }
        }
    }
};

obj.arrfn();
obj.obj.arrfn();
obj.obj.obj.arrfn();
obj.obj.obj.obj.arrfn();

只是如果改成傳統函式的話,規則又會跟之前的一樣,在被呼叫的時候,前一個的物件為 this 的指向。

https://ithelp.ithome.com.tw/upload/images/20200519/20121770xTNeXHhNFW.png

3. This 不同,導致 DOM 的 This 指向也不同

const ele = document.querySelector('p');
ele.addEventListener('click', function () {
    console.log(this);
});

一般來說,這樣撰寫以後,點擊畫面上的 p 元素,this 會指向該 p 元素的 DOM。

https://ithelp.ithome.com.tw/upload/images/20200519/20121770burVdgAn7p.png

但如果用箭頭函式撰寫的話~

const ele = document.querySelector('p');
ele.addEventListener('click', () => {
    console.log(this);
});

https://ithelp.ithome.com.tw/upload/images/20200519/20121770BMbtT1VcOY.png

就會指向全域的物件 window 身上。

4. 也無法透過 call, apply, bind 重新給予 this 的指向

因為箭頭函式沒有自己的 this,所以就算使用 call, apply, bind 重新給予 this 的指向,也無法改變。

const family = {
    myName: '小明家'
};

const fn = (para1, para2) => {
    console.log(this, para1, para2);
};

fn.call(family, '小明', '杰倫');

https://ithelp.ithome.com.tw/upload/images/20200519/20121770z8PIruj3aM.png

5. 不具有 prototype,故無法作為建構函式使用

const Fn = function (a) {
    this.a = a;
}

const ArrowFn = (a) => {
    this.a = a;
}

console.log('Fn', Fn.prototype);
console.log('ArrowFn', ArrowFn.prototype);

const instanceFn = new Fn('a');
const instanceArrowFn = new ArrowFn('a');

https://ithelp.ithome.com.tw/upload/images/20200519/20121770Bu588LzClA.png

以上就是五個傳統函式與箭頭函式不同的地方,其中第二點最容易搞混,要搞清楚再往下走會比較好喔!

沒問題的話就繼續吧!汪汪~


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言